/**
 * Copyright (C) 2008 Christopher Allen Ogden
 *
 *     This file is part of Odysi.
 *
 *  Odysi is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Odysi is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Odysi.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <stdio.h>
#include "genPackets.h"

namespace {
    static const std::string errorLoginNameLength("Login name exceeds maximum length.");
    static const std::string errorPasswordLength("Password exceeds maximum length.");
}

namespace genPacket {

    Packet login(const std::string &name, const std::string &pass)
    {
        // Make sure the name isn't too long.
        if (name.length() > maxLoginNameLength) {
            throw std::runtime_error(errorLoginNameLength);
        }

        // Make sure the password isn't too long.
        if (pass.length() > maxPasswordLength) {
            throw std::runtime_error(errorPasswordLength);
        }

        LoginPacket lp;
        memset(&lp, 0, sizeof(lp));

        lp.cmd = PH_LOGIN;
        memcpy(lp.name, name.c_str(), name.length());
        memcpy(lp.pass, pass.c_str(), pass.length());

        return Packet(reinterpret_cast<void *>(&lp), sizeof(lp));
    }

    Packet moveRequest(int dir)
    {
        MoveRequestPacket mp;
        mp.cmd = PH_MOVE_REQUEST;
        mp.dir = dir;
        return Packet(reinterpret_cast<void *>(&mp), sizeof(mp));
    }

    Packet loginOK(void)
    {
        SimplePacket sp;
        sp.cmd = PH_LOGIN_OK;
        return Packet(reinterpret_cast<void *>(&sp), sizeof(sp));
    }

    Packet loginFail(void)
    {
        SimplePacket sp;
        sp.cmd = PH_LOGIN_FAIL;
        return Packet(reinterpret_cast<void *>(&sp), sizeof(sp));
    }

    Packet addCharacter(unsigned int x, unsigned int y, int z, unsigned int mobID, unsigned int id, float red, float green, float blue, float alpha)
    {
        AddCharacterPacket ac;
        ac.cmd = PH_ADD_CHARACTER;
        ac.x = x;
        ac.y = y;
        ac.z = z;
        ac.mobID = mobID;
        ac.id = id;
        ac.red = red;
        ac.green = green;
        ac.blue = blue;
        ac.alpha = alpha;
        return Packet(reinterpret_cast<void *>(&ac), sizeof(ac));
    }

    Packet moveObject(unsigned int id, int xOff, int yOff, int zOff)
    {
        MoveObjectPacket mp;
        mp.cmd = PH_MOVE_OBJECT;
        mp.id = id;
        mp.xOff = xOff;
        mp.yOff = yOff;
        mp.zOff = zOff;
        return Packet(reinterpret_cast<void *>(&mp), sizeof(mp));
    }

    unsigned int getPacketLength(const unsigned char * const packet, unsigned int length)
    {
        if (length < 1) return 0;
        switch(packet[0]) {
            case PH_LOGIN: return sizeof(LoginPacket);
            case PH_LOGIN_OK: return sizeof(SimplePacket);
            case PH_LOGIN_FAIL: return sizeof(SimplePacket);
            case PH_ADD_CHARACTER: return sizeof(AddCharacterPacket);
            case PH_MOVE_REQUEST: return sizeof(MoveRequestPacket);
            case PH_MOVE_OBJECT: return sizeof(MoveObjectPacket);
            case PH_LUA_REMOTE_CALL:
                if (length >= sizeof(size_t) + sizeof(int) + 1) {
                    size_t size;
                    memcpy(&size, packet + sizeof(int) + 1, sizeof(size_t));
                    return size;
                }
                break;
        }
        return 0;
    }
}
